package com.example.demo.service;

import com.example.demo.dao.TBizOrderDAO;
import com.example.demo.po.TBizOrder;
import com.example.demo.po.WxPayRecord;
import com.example.demo.util.DateUtil;
import com.example.demo.util.StringUtil;
import com.example.demo.util.WxUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@Service
public class WxPayService {

    @Autowired
    TBizOrderService tBizOrderService;

    public String resultofPayFor(HttpServletResponse response,
                                 HttpServletRequest request) throws IOException {
        String result = "";
        // 解析各种数据
        String sign = "";// 获取签名
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        String FEATURE = null;
        try {
            FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
            dbf.setFeature(FEATURE, true);
            FEATURE = "http://xml.org/sax/features/external-general-entities";
            dbf.setFeature(FEATURE, false);
            FEATURE = "http://xml.org/sax/features/external-parameter-entities";
            dbf.setFeature(FEATURE, false);
            FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
            dbf.setFeature(FEATURE, false);
            dbf.setXIncludeAware(false);
            dbf.setExpandEntityReferences(false);
        } catch (ParserConfigurationException e) {
            // This should catch a failed setFeature feature
            System.err.println("ParserConfigurationException was thrown. The feature '" +
                    FEATURE + "' is probably not supported by your XML processor.");
        }
        try {
            System.out.println("小程序回调======str");
            InputStream is = request.getInputStream();
            String xml = inputStream2String(is, "UTF-8");
            Map<String, String> params = new HashMap<String, String>();
            DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
            Document document = documentBuilder.parse(new ByteArrayInputStream(xml.getBytes()));
            Element rootElement = document.getDocumentElement();
            NodeList studentNodeList = rootElement.getChildNodes();
            for (int i = 0; i < studentNodeList.getLength(); i++) {
                Node appElement = studentNodeList.item(i);
                String mapkey = appElement.getNodeName();
                String mapval = appElement.getTextContent();
                if(!"sign".equals(mapkey))params.put(mapkey, mapval);
                if("sign".equals(mapkey))sign=mapval;
            }
            System.out.println(params.toString());
            System.out.println(params.toString()+"小程序开始回调======"+xml);
            System.out.println("小程序开始回调======"+params.get("return_code"));//返回状态码
            String return_code = params.get("return_code");
            System.out.println("小程序开始回调======"+params.get("out_trade_no"));//商户订单号
            String id = params.get("out_trade_no");
            System.out.println("小程序开始回调======"+params.get("total_fee"));//订单金额
            String ticketid = params.get("transaction_id");
            System.out.println("小程序开始回调======"+params.get("cash_fee"));//现金支付金额
            System.out.println("小程序回调======end");
            //加密前验证notify支付订单网关
            //MD5加密
            String endsign = "";
            endsign = WxUtil.generateSignature(params, WxUtil.key);
            System.out.println(endsign);
            // 验证签名
            if (sign.equals(endsign)) {
                if(StringUtil.isNotBlank(id) && "SUCCESS".equals(return_code)){
                    TBizOrder order = new TBizOrder();
                    order.setOrderid(id);
                    order.setOrderstate("2");
                    order.setTicketid(ticketid);
                    order.setPaytype("1");
                    WxPayRecord wpr = new WxPayRecord();
                    wpr.setPrice(params.get("total_fee"));
                    wpr.setPayType("wx");
                    wpr.setOrderId(id);
                    wpr.setTicketId(ticketid);
                    wpr.setPayTime(DateUtil.formatDate(new Date()));
                    boolean a = tBizOrderService.payTrue(order,wpr);
                    if(a) {
                        result = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                                + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                        System.out.println(result);
                        result = setXml("SUCCESS", "OK");
                        System.out.println(result);
                    }else{
                        System.err.println("订单修改失败！");
                        result = setXml("fail", "订单修改失败");
                    }

                }else{
                    System.err.println("参数缺失！");
                    result = setXml("fail", "参数缺失！");
                }
            } else {
                System.err.println("签名不一致！");
                result = setXml("fail", "签名不一致！");
            }
        } catch (Exception e) {
            // TODO 自动生成的 catch 块
            System.out.println("小程序开始回调======错误========");
            e.printStackTrace();
        }
        return result;
    }

    /**
     * InputStream流转换成String字符串
     * @param inStream InputStream流
     * @param encoding 编码格式
     * @return String字符串
     */
    public static String inputStream2String(InputStream inStream, String encoding){
        String result = null;
        try {
            if(inStream != null){
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                byte[] tempBytes = new byte[1000];
                int count = -1;
                while((count = inStream.read(tempBytes, 0, 1000)) != -1){
                    outStream.write(tempBytes, 0, count);
                }
                tempBytes = null;
                outStream.flush();
                result = new String(outStream.toByteArray(), encoding);
            }
        } catch (Exception e) {
            result = null;
        }
        return result;
    }

    //通过xml 发给微信消息
    public static String setXml(String return_code, String return_msg) {
        SortedMap<String, String> parameters = new TreeMap<String, String>();
        parameters.put("return_code", return_code);
        parameters.put("return_msg", return_msg);
        return "<xml><return_code><![CDATA[" + return_code + "]]>" +
                "</return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }


}
